package com.ncmmall.application.business.order.wechat;

import com.feijin.commons.securitys.MD5HashUtils;
import com.google.common.base.Strings;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by linhon on 2018/1/8
 */
public class WechatRefundUtil {

    private WechatRefundUtil() {
    }

    /**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     */
    public static String mapToXml(Map<String, String> data) throws TransformerException, IOException, ParserConfigurationException {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.newDocument();

        Element root = document.createElement("xml");
        document.appendChild(root);

        for (Map.Entry<String, String> entry : data.entrySet()) {
            Element filed = document.createElement(entry.getKey());
            filed.appendChild(document.createTextNode(Strings.nullToEmpty(entry.getValue()).trim()));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");

        try (StringWriter writer = new StringWriter()) {
            StreamResult result = new StreamResult(writer);
            transformer.transform(source, result);
            return writer.toString();
        }
    }


    /**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     */
    public static Map<String, String> xmlToMap(String strXML) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = documentBuilder.parse(new ByteArrayInputStream(strXML.getBytes(StandardCharsets.UTF_8)));
        doc.getDocumentElement().normalize();
        NodeList nodeList = doc.getDocumentElement().getChildNodes();
        Map<String, String> data = new HashMap<>();
        for (int idx = 0; idx < nodeList.getLength(); idx++) {
            Node node = nodeList.item(idx);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) node;
                data.put(element.getNodeName(), element.getTextContent());
            }
        }
        return data;
    }

    private static byte[] decodeBase64(String input) {
        return Base64.getMimeDecoder().decode(input);
    }


    private static String Aes256Decode(String bytes, String key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(MD5HashUtils.MD5(key).toLowerCase().getBytes(), "AES");
        //TODO
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return new String(cipher.doFinal(decodeBase64(bytes)));
    }


    public static String buildResponse(String returnCode, String returnMsg) {
        Map<String, String> data = new HashMap<>();
        data.put("returnCode", returnCode);
        data.put("returnMsg", returnMsg);
        try {
            return mapToXml(data);
        } catch (Exception e) {
            return null;
        }
    }
}
